#pragma once
#include <iostream>
#include <jsoncpp/json/json.h>
#include <string>
#include <functional>
#include "Socket.hpp"
#include "InetAddr.hpp"
using namespace SocketModule;
using namespace std;
class Request
{
public:
    Request() {}
    Request(int x, int y, char oper)
        : _x(x), _y(y), _oper(oper)
    {
    }
    string Serialize()
    {
        Json::Value data;
        data["x"] = _x;
        data["y"] = _y;
        data["oper"] = _oper;
        Json::FastWriter writer;
        cout<<writer.write(data);
        return writer.write(data);
    }
    void DeSerialize(string &message)
    {
        Json::Value data;
        Json::Reader reader;
        reader.parse(message, data);
        _x = data["x"].asInt();
        _y = data["y"].asInt();
        _oper = data["oper"].asInt();
    }
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }

private:
    int _x;
    int _y;
    char _oper;
};
class Response
{
public:
    Response() {}
    Response(int result, int code)
        : _result(result), _code(code)
    {
    }
    string Serialize()
    {
        Json::Value data;
        data["result"] = _result;
        data["code"] = _code;
        Json::FastWriter writer;
        return writer.write(data);
    }
    void DeSerialize(string &message)
    {
        Json::Value data;
        Json::Reader reader;
        reader.parse(message, data);
        _result = data["result"].asInt();
        _code = data["code"].asBool();
    }
    void ShowResult()
    {
        cout << "result[" << _result << "]:code[" << _code << "]" << endl;
    }
    int Result() { return _result; }
    bool Code() { return _code; }
    void SetResult(int ret) { _result = ret; }
    void SetCode(int f) { _code = f; }

private:
    int _result;
    int _code;
};
const string sep = "\r\n";
using func_t = function<Response(Request &)>;
class Protocol
{
public:
    Protocol() {};
    Protocol(func_t func)
        : _func(func)
    {
    }
    string EnCode(string &jsonstr)
    {
        size_t len = jsonstr.size();
        return to_string(len) + sep + jsonstr + sep;
    }
    bool DeCode(string &buffer, string *package)
    {
        int pos = buffer.find(sep);
        if (pos == string::npos)
            return false;
        string lenStr = buffer.substr(0, pos);
        int lenTarget = lenStr.size() + stoi(lenStr) + 2 * sep.size();
        if (buffer.size() < lenTarget)
            return false;
        *package = buffer.substr(pos + sep.size(), stoi(lenStr));
        buffer.erase(0, lenTarget);
        return true;
    }
    void GetRequest(shared_ptr<Socket> &sock, InetAddr &addr)
    {
        while (true)
        {
            string json_package; //?
            int n = sock->Recv(&json_package);
            if (n == 0)
            {
                LOG(Level::INFO) << "client " << addr.tostring_ip() << " exit";
                break;
            }
            else if (n < 0)
            {
                LOG(Level::WARING) << "Recv fail";
                break;
            }
            else
            {
                // 解报包
                string json_str;
                while (DeCode(json_package, &json_str))
                {
                    // 反序列化
                    Request req;
                    req.DeSerialize(json_str);
                    // 处理
                    Response resp = _func(req);
                    // 序列化
                    string send_str = resp.Serialize();
                    // 加报头
                    send_str = EnCode(send_str);
                    // 发送
                    sock->Send(send_str);
                }
            }
        }
    }
    bool GetResponse(shared_ptr<Socket> &sock, string *buffer, Response *rsp)
    {
        while (true)
        {
            int n = sock->Recv(buffer);
            if (n == 0)
            {
                LOG(Level::WARING) << "server exit";
                return false;
            }
            else if (n < 0)
            {
                LOG(Level::WARING) << "client Recv fail";
                return false;
            }
            else
            {
                // 解包
                string json_str;
                if (!DeCode(*buffer, &json_str)) continue;
                // 反序列化
                rsp->DeSerialize(json_str);
                return true;
            }
        }
    }
    string BuildRequestString(int x, int y, char oper)
    {
        Request req(x, y, oper);
        string json_str = req.Serialize();
        return EnCode(json_str);
    }
    string Execute(string package)
    {
        Request req;
        //反序列化
        req.DeSerialize(package);
        //处理
        Response resp = _func(req);
        //序列化
        string json_str = resp.Serialize();
        //打包(加报头)
        return EnCode(json_str);
    }
private:
    func_t _func;
};


